home *** CD-ROM | disk | FTP | other *** search
/ Night Owl 6 / Night Owl's Shareware - PDSI-006 - Night Owl Corp (1990).iso / 019a / opbgd113.zip / OPBIGED.IN1 < prev    next >
Text File  |  1991-10-21  |  42KB  |  1,563 lines

  1.  
  2.   procedure BigEditor.GoToMarker(var M : MarkerRec);
  3.   begin
  4.     with M do begin
  5.       if LP = nil then exit;
  6.       GoToLinePtr(LP);
  7.       CursorToCol(CP);
  8.     end;
  9.   end;
  10.  
  11.   function BigEditor.MemForBlock : LongInt;
  12.   var
  13.     P : PLine;
  14.     L : LongInt;
  15.   begin
  16.     P := beBlockBegin.LP;
  17.     L := LongInt(P^.Size) + SizeOf(LineNode);
  18.     while (P <> nil) and (P <> beBlockEnd.LP) do begin
  19.       P := PLine(P^.dlNext);
  20.       Inc(L, LongInt(P^.Size) + SizeOf(LineNode));
  21.     end;
  22.     MemForBlock := L;
  23.   end;
  24.  
  25.   function BigEditor.BlockContiguous : Boolean;
  26.   var
  27.     P : PLine;
  28.   begin
  29.     BlockContiguous := False;
  30.     if (beBlockBegin.LP = nil) or (beBlockEnd.LP = nil) then exit;
  31.     if (beBlockBegin.LP = beBlockEnd.LP) then begin
  32.       BlockContiguous := (beBlockEnd.CP >= beBlockEnd.CP);
  33.       exit;
  34.     end;
  35.     P := beBlockBegin.LP;
  36.     while P <> nil do begin
  37.       if P = beBlockEnd.LP then begin
  38.         BlockContiguous := True;
  39.         exit;
  40.       end;
  41.       P := PLine(P^.dlNext);
  42.     end;
  43.   end;
  44.  
  45.   function BigEditor.LineInBlock(P : PLine) : Boolean;
  46.   var
  47.     N : PLine;
  48.   begin
  49.     LineInBlock := False;
  50.     if not BlockContiguous then exit;
  51.     N := beBlockBegin.LP;
  52.     while N <> nil do begin
  53.       if N = P then begin
  54.         LineInBlock := True;
  55.         exit;
  56.       end;
  57.       if N = beBlockEnd.LP then exit;
  58.       N := PLine(N^.dlNext);
  59.     end;
  60.   end;
  61.  
  62.   function BigEditor.CursorInBlock(ChkCol : Boolean) : Boolean;
  63.   var
  64.     P : PLine;
  65.   begin
  66.     CursorInBlock := False;
  67.     P := CurLine;
  68.     if not LineInBlock(P) then exit;
  69.     if P = beBlockBegin.LP then
  70.       CursorInBlock := ((not(ChkCol)) or (beBlockBegin.CP <= CurCol))
  71.     else if P = beBlockEnd.LP then
  72.       CursorInBlock := ((not(ChkCol)) or (beBlockEnd.CP >= CurCol))
  73.     else
  74.       CursorInBlock := True;
  75.   end;
  76.  
  77.   procedure BigEditor.CharsInserted(P : PLine; At, Num : Integer);
  78.   var
  79.     I : Integer;
  80.  
  81.     procedure Adjust(var M : MarkerRec; TextMkr : Boolean);
  82.     var
  83.       TC : Integer;
  84.     begin
  85.       with M do
  86.         if (P = LP) and (CP >= At) then begin
  87.           TC := CP;
  88.           if (TextMkr) or (TC > At) then
  89.             if Num > 0 then
  90.               Inc(TC, Num)
  91.             else
  92.               Dec(TC, Abs(Num));
  93.           if TC < At then
  94.             CP := At
  95.           else
  96.             CP := TC;
  97.         end;
  98.     end;
  99.  
  100.   begin
  101.     Adjust(beLastPosition, True);
  102.  
  103.     if P = beBlockBegin.LP then
  104.       Adjust(beBlockBegin, False);
  105.     if P = beBlockEnd.LP then
  106.       Adjust(beBlockEnd, False);
  107.     if not BlockContiguous then
  108.       ClearLongFlag(beOptions, beBlockOn)
  109.     else
  110.       ConnectBlocking;
  111.  
  112.     if beMarkerFlags <> 0 then
  113.       for I := 0 to MaxMarker do
  114.         if P = beMarkers[i].LP then
  115.           Adjust(beMarkers[i], True);
  116.   end;
  117.  
  118.   procedure BigEditor.LineDeleted(P : PLine);
  119.   var
  120.     PN : Word;
  121.     I : Integer;
  122.  
  123.     procedure Adjust(var M : MarkerRec; MT : MarkerType);
  124.     var
  125.       L : Word;
  126.       N : Integer;
  127.     begin
  128.       with M do begin
  129.         if LP = P then
  130.           if MT = mtMarker then
  131.             LP := nil
  132.           else begin
  133.             if MT = mtBlockBegin then
  134.               LP := PLine(LP^.dlNext)
  135.             else
  136.               LP := PLine(LP^.dlPrev);
  137.             CP := 0;
  138.           end;
  139.       end;
  140.     end;
  141.  
  142.   begin
  143.     Adjust(beLastPosition, mtMarker);
  144.  
  145.     PN := LList^.Num(P);
  146.     if beBlockBegin.LP <> nil then
  147.       Adjust(beBlockBegin, mtBlockBegin);
  148.     if beBlockEnd.LP <> nil then
  149.       Adjust(beBlockEnd, mtBlockEnd);
  150.     if not BlockContiguous then
  151.       ClearLongFlag(beOptions, beBlockOn)
  152.     else
  153.       ConnectBlocking;
  154.  
  155.     if beMarkerFlags <> 0 then
  156.       for I := 0 to MaxMarker do
  157.         Adjust(beMarkers[i], mtMarker);
  158.   end;
  159.  
  160.   procedure BigEditor.LinesBroken(P : PLine; At : Integer);
  161.   var
  162.     PN : Word;
  163.     I : Integer;
  164.  
  165.     procedure Adjust(var M : MarkerRec);
  166.     begin
  167.       with M do
  168.         if (LP = P) and (CP >= At) then begin
  169.           LP := PLine(LP^.dlNext);
  170.           Dec(CP, At);
  171.           if CP < 0 then CP := 0;
  172.         end;
  173.     end;
  174.  
  175.   begin
  176.     Adjust(beLastPosition);
  177.  
  178.     PN := LList^.Num(P);
  179.     if beBlockBegin.LP <> nil then
  180.       Adjust(beBlockBegin);
  181.     if beBlockEnd.LP <> nil then
  182.       Adjust(beBlockEnd);
  183.     if not BlockContiguous then
  184.       ClearLongFlag(beOptions, beBlockOn)
  185.     else
  186.       ConnectBlocking;
  187.  
  188.     if beMarkerFlags <> 0 then
  189.       for I := 0 to MaxMarker do
  190.         Adjust(beMarkers[i]);
  191.   end;
  192.  
  193.   procedure BigEditor.LinesJoined(P : PLine; At : Integer);
  194.   var
  195.     I : Integer;
  196.  
  197.     procedure Adjust(var M : MarkerRec);
  198.     begin
  199.       with M do
  200.         if LP = P then begin
  201.           LP := PLine(LP^.dlPrev);
  202.           Inc(CP, At);
  203.         end;
  204.     end;
  205.  
  206.   begin
  207.     Adjust(beLastPosition);
  208.  
  209.     if beBlockBegin.LP <> nil then
  210.       Adjust(beBlockBegin);
  211.     if beBlockEnd.LP <> nil then
  212.       Adjust(beBlockEnd);
  213.     if not BlockContiguous then
  214.       ClearLongFlag(beOptions, beBlockOn)
  215.     else
  216.       ConnectBlocking;
  217.  
  218.     if beMarkerFlags <> 0 then
  219.       for I := 0 to MaxMarker do
  220.         Adjust(beMarkers[i]);
  221.   end;
  222.  
  223.   procedure BigEditor.ConnectBlocking;
  224.     {-walks list, connection proper block marks}
  225.   var
  226.     P : PLine;
  227.     B : Boolean;
  228.   begin
  229.     B := False;
  230.     P := PLine(LList^.Head);
  231.     while P <> nil do begin
  232.       if P = beBlockBegin.LP then
  233.         B := True;
  234.       P^.Blocked := B;
  235.       if P = beBlockEnd.LP then
  236.         B := False;
  237.       P := PLine(P^.dlNext);
  238.     end;
  239.   end;
  240.  
  241.   procedure BigEditor.CleanBlocking;
  242.     {-clears existing blocking}
  243.   var
  244.     P : PLine;
  245.   begin
  246.     P := PLine(LList^.Head);
  247.     while P <> nil do begin
  248.       P^.Blocked := False;
  249.       P := PLine(P^.dlNext);
  250.     end;
  251.   end;
  252.  
  253.   procedure BigEditor.MarkWordAsBlock;
  254.   label
  255.     Again;
  256.   var
  257.     I : Integer;
  258.     C : Integer;
  259.  
  260.     function IsAlpha(C : Char) : Boolean;
  261.     begin
  262.       IsAlpha := not (C in WordDelims);
  263.     end;
  264.  
  265.   begin
  266.     GetCurLine;
  267.     I := LenAsc(Work^);
  268.     if I = 0 then begin
  269.       GotError(epNonFatal,'Empty line');
  270.       exit;
  271.     end;
  272.     Dec(I);
  273.  
  274.     C := CurCol;
  275.     if C > I then
  276.       C := I;
  277.  
  278. Again:
  279.     if IsAlpha(Work^[C]) then begin
  280.       while (C >= 0) and (IsAlpha(Work^[C])) do
  281.         Dec(C);
  282.       Inc(C);
  283.     end
  284.     else if C = I then begin
  285.       while (C >= 0) and (Work^[C] in WordDelims) do
  286.         Dec(C);
  287.       if (C >= 0) then
  288.         goto Again;
  289.     end
  290.     else begin
  291.       while (C < I) and (Work^[C] in WordDelims) do
  292.         Inc(C);
  293.       if C > I then begin
  294.         C := I;
  295.         goto Again;
  296.       end;
  297.     end;
  298.  
  299.     if (C < 0) or (C > I) then begin
  300.       GotError(epNonFatal, 'Can''t define line limits');
  301.       exit;
  302.     end;
  303.  
  304.     beBlockBegin.CP := C;
  305.     while (C <= I) and (IsAlpha(Work^[C])) do
  306.       Inc(C);
  307.     beBlockEnd.CP := C;
  308.  
  309.     beBlockBegin.LP := Cur;
  310.     beBlockEnd.LP := Cur;
  311.     if BlockContiguous then
  312.       ConnectBlocking;
  313.     SetLongFlag(beOptions, beBlockOn+beForceRedraw);
  314.   end;
  315.  
  316.   procedure BigEditor.ChangeCaseBlock(CT : beChangeCaseType);
  317.   var
  318.     P : PLine;
  319.  
  320.     procedure ChangeCharPrim(var C : Char);
  321.     begin
  322.       case CT of
  323.         beToUpper:
  324.           C := Upcase(C);
  325.         beToLower:
  326.           C := Locase(C);
  327.         else begin
  328.           if C in ['A'..'Z'] then
  329.             C := Locase(C)
  330.           else
  331.             C := Upcase(C);
  332.         end;
  333.       end;
  334.     end;
  335.  
  336.     procedure ChangeLinePrim(L : AsciiZPtr; At, Len : Integer);
  337.     var
  338.       M,N : Integer;
  339.     begin
  340.       M := LenAsc(L^)-1;
  341.       if M < At then exit;
  342.       if M > (At+Len) then
  343.         M := At+Len;
  344.       for N := At to M do
  345.         ChangeCharPrim(L^[N]);
  346.     end;
  347.  
  348.   begin
  349.     if (not(BlockContiguous)) or (not(LongFlagIsSet(beOptions, beBlockOn))) then exit;
  350.  
  351.     P := beBlockBegin.LP;
  352.     if P = beBlockEnd.LP then
  353.         {block is in a single line}
  354.       ChangeLinePrim(P^.St, beBlockBegin.CP, beBlockEnd.CP-beBlockBegin.CP)
  355.     else begin
  356.       ChangeLinePrim(P^.St, beBlockBegin.CP, AbsMaxAsciiZ);
  357.       P := PLine(P^.dlNext);
  358.       while P <> beBlockEnd.LP do begin
  359.         ChangeLinePrim(P^.St, 0, AbsMaxAsciiZ);
  360.         P := PLine(P^.dlNext);
  361.       end;
  362.       ChangeLinePrim(P^.St, 0, beBlockEnd.CP);
  363.     end;
  364.     SetLongFlag(beOptions, beForceRedraw);
  365.   end;
  366.  
  367.   function BigEditor.BlockToList(var L : LineList) : Boolean;
  368.   var
  369.     P, N : PLine;
  370.     Siz : LongInt;
  371.   begin
  372.     BlockToList := False;
  373.     L.Clean;
  374.  
  375.     if beBlockBegin.LP = beBlockEnd.LP then begin
  376.       {a single line to copy}
  377.       CopyAsc(beBlockBegin.LP^.St^, beBlockBegin.CP, beBlockEnd.CP-beBlockBegin.CP,
  378.               Temp^);
  379.       New(P, Init(Temp));
  380.       if P = nil then begin
  381.         GotError(epNonFatal+ecOutOfMemory, emInsufficientMemory);
  382.         exit;
  383.       end;
  384.       L.Append(P);
  385.     end
  386.     else begin
  387.       {multiline block to copy}
  388.       N := beBlockBegin.LP;
  389.  
  390.         {copy starting line}
  391.       CopyAsc(N^.St^, beBlockBegin.CP, AbsMaxAsciiZ, Temp^);
  392.       New(P, Init(Temp));
  393.       if P = nil then begin
  394.         GotError(epNonFatal+ecOutOfMemory, emInsufficientMemory);
  395.         exit;
  396.       end;
  397.       L.Append(P);
  398.       N := PLine(N^.dlNext);
  399.  
  400.       while N <> beBlockEnd.LP do begin
  401.         {copy intermediate line(s)}
  402.         New(P, Init(N^.St));
  403.         if P = nil then begin
  404.           GotError(epNonFatal+ecOutOfMemory, emInsufficientMemory);
  405.           exit;
  406.         end;
  407.         L.Append(P);
  408.         N := PLine(N^.dlNext);
  409.       end;
  410.  
  411.         {copy blockend line}
  412.       CopyAsc(N^.St^, 0, beBlockEnd.CP, Temp^);
  413.       New(P, Init(Temp));
  414.       if P = nil then begin
  415.         GotError(epNonFatal+ecOutOfMemory, emInsufficientMemory);
  416.         exit;
  417.       end;
  418.       L.Append(P);
  419.     end;
  420.     BlockToList := True;
  421.   end;
  422.  
  423.   procedure BigEditor.BlockFromList(var L : LineList);
  424.   label
  425.     Breakout;
  426.   var
  427.     P, N, X : PLine;
  428.   begin
  429.     if L.Size = 0 then exit;
  430.  
  431.     GetCurLine;
  432.     if L.Size = 1 then begin
  433.       {a single line to insert:}
  434.       if CurCol > Cur^.lnLen then
  435.         AscPad(Work^, CurCol, Work^);
  436.  
  437.         {update the line}
  438.       InsertAsc(PLine(L.Head)^.St^, Work^, CurCol);
  439.       Status := Cur^.lnUpdate(Work);
  440.       if Status <> 0 then goto BreakOut;
  441.  
  442.         {update blockmarks}
  443.       beBlockBegin.LP := Cur;
  444.       beBlockBegin.CP := CurCol;
  445.       beBlockEnd.LP := Cur;
  446.       beBlockEnd.CP := beBlockBegin.CP + LenAsc(PLine(L.Head)^.St^);
  447.     end
  448.     else begin
  449.       {multiline block to insert: first split the current line at the cursor}
  450.       P := SplitLine(Cur, CurCol);
  451.       if P = nil then goto BreakOut;
  452.       LList^.Place(P, Cur);
  453.  
  454.         {add the first block line}
  455.       N := PLine(L.Head);
  456.       ConcatAsc(Work^, N^.St^, Work^);
  457.       Status := Cur^.lnUpdate(Work);
  458.       if Status <> 0 then goto BreakOut;
  459.  
  460.         {update blockbegin}
  461.       beBlockBegin.LP := Cur;
  462.       beBlockBegin.CP := CurCol;
  463.  
  464.         {walk list inserting intermediate lines}
  465.       X := Cur;
  466.       N := PLine(N^.dlNext);
  467.       while N <> nil do begin
  468.         New(P, Init(N^.St));
  469.         if P = nil then goto BreakOut;
  470.         LList^.Place(P, X);
  471.         X := PLine(X^.dlNext);
  472.         N := PLine(N^.dlNext);
  473.       end;
  474.  
  475.         {update beBlockEnd}
  476.       beBlockEnd.LP := X;
  477.       beBlockEnd.CP := LenAsc(X^.St^);
  478.         {concat following line}
  479.       P := PLine(X^.dlNext);
  480.       if P <> nil then begin
  481.         GetTemp(P);
  482.         ConcatAsc(X^.St^, Temp^, Work^);
  483.         Status := X^.lnUpdate(Work);
  484.         if Status <> 0 then goto Breakout;
  485.         LList^.Delete(P);
  486.       end;
  487.     end;
  488.     ConnectBlocking;
  489.     SetLongFlag(beOptions, beModified+beForceRedraw+beBlockOn);
  490.     exit;
  491.  
  492. BreakOut:
  493.     CleanBlocking;
  494.     FillChar(beBlockBegin, SizeOf(beBlockBegin), 0);
  495.     FillChar(beBlockEnd, SizeOf(beBlockEnd), 0);
  496.     GotError(epFatal+ecOutOfMemory, emInsufficientMemory);
  497.   end;
  498.  
  499.   function BigEditor.DeleteBlockPrim : Boolean;
  500.   var
  501.     P, N : PLine;
  502.     I : Word;
  503.   begin
  504.     DeleteBlockPrim := False;
  505.     if not BlockContiguous then exit;
  506.  
  507.     if beBlockBegin.LP = beBlockEnd.LP then begin
  508.       {single line block}
  509.       N := CurLine;
  510.       P := beBlockBegin.LP;
  511.       GetWork(P);
  512.       DeleteAsc(Work^, beBlockBegin.CP, beBlockEnd.CP-beBlockBegin.CP);
  513.       Status := P^.lnUpdate(Work);
  514.       if Status <> 0 then begin
  515.         GotError(epNonFatal+ecOutOfMemory, emInsufficientMemory);
  516.         exit;
  517.       end;
  518.       if P = N then
  519.         if CurCol > beBlockBegin.CP then
  520.           ChCursor(-(beBlockEnd.CP-beBlockBegin.CP));
  521.     end
  522.     else begin
  523.       N := beBlockBegin.LP;
  524.       GoToLineCol(LList^.Num(N), 0);
  525.       GetWork(N);
  526.       DeleteAsc(Work^, beBlockBegin.CP, AbsMaxAsciiZ);
  527.  
  528.       while PLine(N^.dlNext) <> beBlockEnd.LP do begin
  529.         P := PLine(N^.dlNext);
  530.         LList^.Delete(P);
  531.       end;
  532.  
  533.       P := beBlockEnd.LP;
  534.       GetTemp(P);
  535.       LList^.Delete(P);
  536.       DeleteAsc(Temp^, 0, beBlockEnd.CP);
  537.       ConcatAsc(Work^, Temp^, Work^);
  538.       Status := N^.lnUpdate(Work);
  539.       if Status <> 0 then begin
  540.         GotError(epNonFatal+ecOutOfMemory, emInsufficientMemory);
  541.         exit;
  542.       end;
  543.     end;
  544.  
  545.     FillChar(beBlockBegin, SizeOf(beBlockBegin), 0);
  546.     FillChar(beBlockEnd, SizeOf(beBlockEnd), 0);
  547.     ClearLongFlag(beOptions, beBlockOn);
  548.     SetLongFlag(beOptions, beModified+beForceRedraw);
  549.  
  550.       {if we erased the whole stream, make sure things are safe}
  551.     if LList^.Size = 0 then begin
  552.       Str2Asc('', Work^);
  553.       New(Top, Init(Work));
  554.       LList^.Append(Top);
  555.       LOfs := 0;
  556.       CPos := 1;
  557.       COfs := 0;
  558.     end;
  559.     DeleteBlockPrim := True;
  560.   end;
  561.  
  562.   procedure BigEditor.CopyBlock;
  563.   var
  564.     Siz : LongInt;
  565.   begin
  566.     if (not(beOptionsAreOn(beBlockOn))) or (not(BlockContiguous)) then exit;
  567.  
  568.       {make sure we've got enough mem to do the job}
  569.     Siz := MemForBlock * 2;  {we need twice as much memory for a copy}
  570.     Siz := Siz + MemSafetySize;
  571.     if (Siz > MemAvail) or (MaxAvail < AbsMaxAsciiZ) then begin
  572.       GotError(epNonFatal+ecOutOfMemory, emInsufficientMemory);
  573.       exit;
  574.     end;
  575.  
  576.       {store the block}
  577.     if not BlockToList(TList^) then exit;
  578.  
  579.       {paste it in at the current location}
  580.     BlockFromList(TList^);
  581.     TList^.Clean;
  582.   end;
  583.  
  584.   procedure BigEditor.MoveBlock;
  585.   var
  586.     C : Integer;
  587.     P : PLine;
  588.     Siz : LongInt;
  589.   begin
  590.     if (not(beOptionsAreOn(beBlockOn))) or (not(BlockContiguous)) then
  591.       exit;
  592.  
  593.       {don't try to move the whole stream}
  594.     if (beBlockBegin.LP = PLine(LList^.Head)) and (beBlockEnd.LP = PLine(LList^.Tail)) then
  595.       exit;
  596.  
  597.       {make sure we've got enough mem to do the job}
  598.     Siz := MemForBlock + MemSafetySize;
  599.     if (Siz > MemAvail) or (MaxAvail < AbsMaxAsciiZ) then begin
  600.       GotError(epNonFatal+ecOutOfMemory, emInsufficientMemory);
  601.       exit;
  602.     end;
  603.  
  604.       {move the block: start by saving our current position}
  605.     P := PLine(LList^.Nth(TNum+LOfs));
  606.     C := CurCol;
  607.  
  608.       {store the block}
  609.     if not BlockToList(TList^) then exit;
  610.  
  611.       {delete the block in the main stream}
  612.     if not DeleteBlockPrim then exit;
  613.  
  614.       {restore our display position in the stream}
  615.     GoToLinePtr(P);
  616.     CursorToCol(C);
  617.  
  618.       {paste in the block}
  619.     BlockFromList(TList^);
  620.     TList^.Clean;
  621.   end;
  622.  
  623.   procedure BigEditor.DeleteBlock;
  624.   var
  625.     L : Integer;
  626.   begin
  627.     if (not(beOptionsAreOn(beBlockOn))) or (not(CursorInBlock(True))) then exit;
  628.     if DeleteBlockPrim then ;
  629.   end;
  630.  
  631.   function BigEditor.ReadBlockPrim(var Lst : LineList) : Boolean;
  632.   label
  633.     Breakout;
  634.   var
  635.     Buf : IOBuf;
  636.     F : Text;
  637.     FN : PathStr;
  638.     I : Integer;
  639.     P : PLine;
  640.   begin
  641.     ReadBlockPrim := False;
  642.  
  643.     FN := '';
  644.     if not Edit(mcBlockRead, emBlockRead, True, True, 80, FN) then exit;
  645.     if not ExistFile(FN) then begin
  646.       GotError(epNonFatal+ecFileNotFound, emFileNotFound);
  647.       exit;
  648.     end;
  649.  
  650.     Assign(F, FN);
  651.     SetTextBuf(F, Buf, MaxFBuf);
  652.     Reset(F);
  653.     I := IoResult;
  654.     if I <> 0 then begin
  655.       GotError(epNonFatal+I, emOpenError);
  656.       exit;
  657.     end;
  658.  
  659.     Lst.Clean;
  660.     while not EOF(F) do begin
  661.       if not ReadLnAsc(F, Work^) then begin
  662.         GotError(epNonFatal+ecDeviceRead, emReadError);
  663.         goto Breakout;
  664.       end;
  665.  
  666.       New(P, Init(Work));
  667.       if P = nil then begin
  668.         GotError(epNonFatal+ecOutOfMemory, emInsufficientMemory);
  669.         goto BreakOut;
  670.       end;
  671.       Lst.Append(P);
  672.     end;
  673.  
  674.     ReadBlockPrim := True;
  675.  
  676. Breakout:
  677.     Close(F);  if IoResult = 0 then ;
  678.   end;
  679.  
  680.   procedure BigEditor.ReadBlock;
  681.   begin
  682.     if not ReadBlockPrim(TList^) then exit;
  683.     BlockFromList(TList^);
  684.   end;
  685.  
  686.   procedure BigEditor.WriteBlock(ToPrn : Boolean);
  687.   label
  688.     Breakout;
  689.   var
  690.     Buf : IOBuf;
  691.     F : Text;
  692.     FN : PathStr;
  693.     I : Integer;
  694.     P : PLine;
  695.  
  696.     function WriteLine(P : AsciiZPtr) : Integer;
  697.     var
  698.       N : Integer;
  699.     begin
  700.       N := 0;
  701.       if not WriteAsc(F, P^) then
  702.         I := ecDeviceWrite
  703.       else begin
  704.         Write(F, ^M^J);
  705.         I := IoResult;
  706.       end;
  707.       WriteLine := I;
  708.     end;
  709.  
  710.   begin
  711.     if (not(BlockContiguous)) or
  712.        (not(LongFlagIsSet(beOptions, beBlockOn))) then exit;
  713.  
  714.     if ToPrn then
  715.       FN := 'LPT'+beLPTNum
  716.     else begin
  717.       FN := '';
  718.       if not Edit(mcBlockWrite, emBlockWrite, True, True, 80, FN) then exit;
  719.  
  720.       if ExistFile(FN) then
  721.         if YesNo(0, 'File exists.  Overwrite?', beNo, False) = beNo then exit;
  722.     end;
  723.  
  724.     Assign(F, FN);
  725.     SetTextBuf(F, Buf, MaxFBuf);
  726.     Rewrite(F);
  727.     I := IoResult;
  728.     if I <> 0 then begin
  729.       GotError(epNonFatal+I, emOpenError);
  730.       exit;
  731.     end;
  732.  
  733.     P := beBlockBegin.LP;
  734.     GetWork(P);
  735.     if P = beBlockEnd.LP then begin
  736.       DeleteAsc(Work^, beBlockEnd.CP, AbsMaxAsciiZ);
  737.       DeleteAsc(Work^, 0, beBlockBegin.CP);
  738.       I := WriteLine(Work);
  739.       if I <> 0 then
  740.         GotError(epNonFatal+I, emWriteError);
  741.     end
  742.     else begin
  743.       DeleteAsc(Work^, 0, beBlockBegin.CP);
  744.       I := WriteLine(Work);
  745.       if I <> 0 then begin
  746.         GotError(epNonFatal+I, emWriteError);
  747.         goto Breakout;
  748.       end;
  749.       P := PLine(P^.dlNext);
  750.  
  751.       while P <> beBlockEnd.LP do begin
  752.         GetWork(P);
  753.         I := WriteLine(Work);
  754.         if I <> 0 then begin
  755.           GotError(epNonFatal+I, emWriteError);
  756.           goto Breakout;
  757.         end;
  758.         P := PLine(P^.dlNext);
  759.       end;
  760.  
  761.       GetWork(P);
  762.       DeleteAsc(Work^, beBlockEnd.CP, AbsMaxAsciiZ);
  763.       I := WriteLine(Work);
  764.       if I <> 0 then
  765.         GotError(epNonFatal+I, emWriteError);
  766.     end;
  767.  
  768. Breakout:
  769.     Close(F);  if IoResult <> 0 then ;
  770.   end;
  771.  
  772.   procedure BigEditor.CopyToClipboard(Cut : Boolean);
  773.   var
  774.     Siz : LongInt;
  775.   begin
  776.     if (not(BlockContiguous)) then exit;
  777.  
  778.     Siz := MemForBlock + MemSafetySize;
  779.     if (Siz > MemAvail) or (MaxAvail < AbsMaxAsciiZ) then begin
  780.       GotError(epNonFatal+ecOutOfMemory, emInsufficientMemory);
  781.       exit;
  782.     end;
  783.  
  784.     if not BlockToList(Clipboard) then exit;
  785.     if not Cut then
  786.       ClearLongFlag(beOptions, beBlockOn)
  787.     else
  788.       if DeleteBlockPrim then ;
  789.     SetLongFlag(beOptions, beForceRedraw);
  790.   end;
  791.  
  792.   procedure BigEditor.PasteFromClipboard;
  793.   begin
  794.     if Clipboard.Size > 0 then
  795.       BlockFromList(Clipboard);
  796.   end;
  797.  
  798.   procedure BigEditor.IndentBlock(Spaces : Integer);
  799.   label
  800.     Breakout;
  801.   var
  802.     P : PLine;
  803.     C : PLine;
  804.     I : Integer;
  805.     N : Integer;
  806.     S : String;
  807.   begin
  808.     if (not(BlockContiguous)) or
  809.        (not(LongFlagIsSet(beOptions, beBlockOn))) or
  810.        (not(CursorInBlock(False))) then exit;
  811.     if beBlockBegin.LP = beBlockEnd.LP then exit;
  812.  
  813.     C := CurLine;
  814.     DropMarker(C, CurCol);
  815.  
  816.     I := Abs(Spaces);
  817.     S := CharStr(' ', I);
  818.  
  819.     P := beBlockBegin.LP;
  820.     GetWork(P);
  821.  
  822.     if Spaces > 0 then begin
  823.       InsertStr(S, Work^, beBlockBegin.CP);
  824.       Status := P^.lnUpdate(Work);
  825.       if Status <> 0 then goto Breakout;
  826.       CharsInserted(P, beBlockBegin.CP, I);
  827.       P := PLine(P^.dlNext);
  828.  
  829.       while (P <> PLine(beBlockEnd.LP^.dlNext)) do begin
  830.         if (P <> beBlockEnd.LP) or (beBlockEnd.CP > 0) then begin
  831.           GetWork(P);
  832.           InsertStr(S, Work^, 0);
  833.           Status := P^.lnUpdate(Work);
  834.           if Status <> 0 then goto Breakout;
  835.           if (P = C) or (P = beBlockEnd.LP) then
  836.             CharsInserted(P, 0, I);
  837.         end;
  838.         P := PLine(P^.dlNext);
  839.       end;
  840.     end
  841.     else begin
  842.       N := 0;
  843.       while (N < I) and (Work^[beBlockBegin.CP+N] = ' ') do Inc(N);
  844.       DeleteAsc(Work^, beBlockBegin.CP, N);
  845.       Status := P^.lnUpdate(Work);
  846.       if Status <> 0 then goto Breakout;
  847.       CharsInserted(P, beBlockBegin.CP, -N);
  848.       P := PLine(P^.dlNext);
  849.  
  850.       while (P <> PLine(beBlockEnd.LP^.dlNext)) do begin
  851.         if (P <> beBlockEnd.LP) or (beBlockEnd.CP > 0) then begin
  852.           GetWork(P);
  853.           N := 0;
  854.           while (N < I) and (Work^[beBlockBegin.CP+N] = ' ') do Inc(N);
  855.           DeleteAsc(Work^, 0, N);
  856.           Status := P^.lnUpdate(Work);
  857.           if Status <> 0 then goto Breakout;
  858.           if (P = C) or (P = beBlockEnd.LP) then
  859.             CharsInserted(P, 0, -N);
  860.         end;
  861.         P := PLine(P^.dlNext);
  862.       end;
  863.     end;
  864.  
  865.     N := CurCol+Spaces;
  866.     if N < 0 then N := 0;
  867.     CursorToCol(N);
  868.     SetLongFlag(beOptions, beModified+beForceRedraw);
  869.     exit;
  870.  
  871. Breakout:
  872.     if Status = 0 then Status := ecOutOfMemory;
  873.     GotError(epNonFatal+Status, emInsufficientMemory);
  874.   end;
  875.  
  876. {-----------------------------------------------------------------------------}
  877.  
  878.   procedure BigEditor.TextSearch(Prompt : Boolean; SearchType : beSearchType);
  879.   label
  880.     ExitPoint;
  881.   var
  882.     SaveRec : StreamStateRec;
  883.     SaveIdx : Integer;
  884.     Hits, Replacements : Integer;
  885.     TSrch : String[MaxSearchLen];
  886.     N : Integer;
  887.     YN : Byte;
  888.  
  889.     procedure StUpcaseAsc(P : AsciiZPtr);
  890.     var
  891.       I : Integer;
  892.     begin
  893.       i := 0;
  894.       while P^[i] <> #0 do begin
  895.         P^[i] := UpCase(P^[i]);
  896.         Inc(I);
  897.       end;
  898.     end;
  899.  
  900.     procedure ReplaceText(Curr : AsciiZPtr; Repl : String; Start, Len : Integer);
  901.     begin
  902.       DeleteAsc(Curr^, Start, Len);
  903.       InsertStr(Repl, Curr^, Start);
  904.     end;
  905.  
  906.     function NextMatch(StartLine : PLine; Srch : String) : PLine;
  907.       {!!.13 - Completely rewritten for better performance and a bug fix}
  908.     var P : PLine;
  909.         T : String;
  910.         W : Word;
  911.     begin
  912.       NextMatch := NIL;
  913.       P := StartLine;
  914.       if P = NIL then exit;
  915.  
  916.       while P <> NIL do begin
  917.         if NoCase then
  918.           W := SearchUC(P^.St^[SaveIdx], P^.Len-SaveIdx-1, Srch[1], Length(Srch))
  919.         else
  920.           W := Search(P^.St^[SaveIdx], P^.Len-SaveIdx-1, Srch[1], Length(Srch));
  921.         if W <> $FFFF then begin
  922.           SaveIdx := W;
  923.           NextMatch := P;
  924.           exit;
  925.         end;
  926.  
  927.         SaveIdx := 0;
  928.         if Backwards then begin
  929.           P := PLine(P^.dlPrev);
  930.           Dec(TNum);
  931.         end
  932.         else begin
  933.           P := PLine(P^.dlNext);
  934.           Inc(TNum);
  935.         end;
  936.       end;
  937.     end;
  938.  
  939.   begin
  940.       {if a reSearch and no prev search performed, quit}
  941.     if (NOT(Prompt)) and (SearchType = bescSearch) and (SearchLine = NIL) then
  942.       exit;
  943.  
  944.     if (Prompt) then begin
  945.       if NOT Edit(0, 'Search for: ', False, False, MaxSearchLen, beSearchSt) then
  946.         exit;
  947.  
  948.       if (SearchType = bescReplace) then begin
  949.         if NOT Edit(0, 'Replace with: ', False, False, MaxSearchLen, beReplaceSt) then
  950.           exit;
  951.       end;
  952.  
  953.       if NOT Edit(0, 'Options: ', True, True, MaxSearchOptions, beOptionSt) then
  954.         exit;
  955.  
  956.       Replacements := 0;
  957.       NoCase := False;
  958.       Backwards := False;
  959.       NoConfirm := False;
  960.       BlockOnly := False;
  961.       Global := False;
  962.       for N := 1 to Length(beOptionSt) do
  963.         case Upcase(beOptionSt[N]) of
  964.           beBackward  : Backwards := True;
  965.           beNoCase    : NoCase := True;
  966.           beNoConfirm : NoConfirm := True;
  967.           beBlockOnly : BlockOnly := True;
  968.           beGlobal    : Global := Prompt;
  969.         end;
  970.     end;
  971.  
  972.       {save the current state of the stream}
  973.     SaveStatePrim(SaveRec);
  974.     SetLongFlag(beOptions, beSearching);
  975.  
  976.       {adjust for case sensitivity}
  977.     if NoCase then
  978.       TSrch := StUpCase(beSearchSt)
  979.     else
  980.       TSrch := beSearchSt;
  981.  
  982.       {get the current line to start the search}
  983.     SearchLine := CurLine;
  984.     SaveIdx := CurCol;
  985.  
  986.       {adjust for Backwards search}
  987.     if Backwards then begin
  988.       ClearLongFlag(beOptions, beHighlightBack);
  989.       Dec(SaveIdx);
  990.     end
  991.     else begin
  992.       SetLongFlag(beOptions, beHighlightBack);
  993.       if (SearchType = bescSearch) and (not(Prompt)) then              {!!.13}
  994.         Inc(SaveIdx);                                                  {!!.13}
  995.     end;
  996.  
  997.       {if global and not re-search, adjust to top/bottom of stream}
  998.     if (Prompt) and (Global) then begin
  999.       if Backwards then begin
  1000.         SearchLine := PLine(LList^.Tail);
  1001.         SaveIdx := SearchLine^.lnLen;
  1002.       end
  1003.       else begin
  1004.         SearchLine := PLine(LList^.Head);
  1005.         SaveIdx := 1;
  1006.       end;
  1007.     end;
  1008.  
  1009.       {adjust so SearchLine is the top-of-screen line}
  1010.     Top := SearchLine;
  1011.     TNum := LList^.Num(Top);
  1012.     LOfs := 0;
  1013.  
  1014.     YN := beYes;
  1015.     Hits := 0;
  1016.  
  1017.       {search for next match:}
  1018.     while True do begin
  1019.       SearchLine := NextMatch(SearchLine, TSrch);
  1020.       if (SearchLine = NIL) or
  1021.          ((BlockOnly) and (NOT(LineInBlock(SearchLine)))) then begin
  1022.         if (SearchType <> bescReplace) or (Hits = 0) then
  1023.           GotError(epNonFatal+ecStringNotFound, emStringNotFound);
  1024.         goto ExitPoint;
  1025.       end;
  1026.       Inc(Hits);
  1027.  
  1028.         {make it displayable}
  1029.       Top := SearchLine;
  1030.       TNum := LList^.Num(Top);
  1031.       LOfs := 0;
  1032.  
  1033.         {try to center the line in the screen}
  1034.       while (Top^.dlPrev <> NIL) and (LOfs < (Height div 2)) do begin
  1035.         Top := PLine(Top^.dlPrev);
  1036.         Dec(TNum);
  1037.         Inc(LOfs);
  1038.       end;
  1039.  
  1040.         {position the cursor}
  1041.       if Backwards then
  1042.         CursorToCol(SaveIdx)
  1043.       else
  1044.         CursorToCol(SaveIdx+Length(beSearchSt)-1);
  1045.  
  1046.       SetLongFlag(beOptions, beForceRedraw);
  1047.       UpdateContents;
  1048.       SaveStatePrim(SaveRec);
  1049.  
  1050.       if SearchType = bescSearch then begin
  1051.         while NOT cwCmdPtr^.cpKeyPressed do ;
  1052.         goto ExitPoint;
  1053.       end
  1054.       else begin
  1055.         if NOT NoConfirm then begin
  1056.           YN := YesNo(0, 'Replace?', beNo, True);
  1057.           NoConfirm := (YN = beAll);
  1058.           if (YN = beQuit) then
  1059.             goto ExitPoint;
  1060.         end;
  1061.         if YN <> beNo then begin
  1062.           GetTemp(SearchLine);                                         {!!.13}
  1063.           ReplaceText(Temp, beReplaceSt, SaveIdx, Length(beSearchSt));
  1064.           Status := SearchLine^.lnUpdate(Temp);
  1065.           if Status <> 0 then begin
  1066.             GotError(epNonFatal+ecOutOfMemory, emInsufficientMemory);
  1067.             goto ExitPoint;
  1068.           end;
  1069.           inc(Replacements);
  1070.           SetLongFlag(beOptions, beForceRedraw);
  1071.           UpdateContents;
  1072.         end;
  1073.         if Backwards then
  1074.           Dec(SaveIdx)
  1075.         else if Length(beReplaceSt) > Length(beSearchSt) then
  1076.           Inc(SaveIdx, Length(beReplaceSt))
  1077.         else
  1078.           Inc(SaveIdx, Length(beSearchSt));
  1079.       end;
  1080.     end;
  1081.  
  1082. ExitPoint:
  1083.     RestoreStatePrim(SaveRec);
  1084.     if (SearchType = bescReplace) and (Replacements > 0) then
  1085.       SetLongFlag(beOptions, beModified);
  1086.     ClearLongFlag(beOptions, beSearching);
  1087.     SetLongFlag(beOptions, beForceRedraw);
  1088.     UpdateContents;
  1089.   end;
  1090.  
  1091. {----------------------------------------------------------------------------}
  1092.  
  1093.   procedure BigEditor.ReformatParagraph;
  1094.   label
  1095.     BreakOut;
  1096.   var
  1097.     B, X, Q : Integer;
  1098.     P, N : PLine;
  1099.   begin
  1100.     if not LongFlagIsSet(beOptions, beWordWrap) then exit;
  1101.  
  1102.       {get the current line}
  1103.     Q := 0;
  1104.     GetCurLine;
  1105.     B := LeadingWhite(Cur);
  1106.     P := Cur;
  1107.  
  1108.       {skip white lines}
  1109.     while (P^.dlNext <> nil) and (P^.lnLen = 0) do begin
  1110.       P := PLine(P^.dlNext);
  1111.       ChLine(1);
  1112.     end;
  1113.     if P^.dlNext = nil then
  1114.       exit;
  1115.  
  1116.       {run the loop}
  1117.     while (P <> nil) and (P^.lnLen > 0) do begin
  1118.       GetWork(P);
  1119.  
  1120.         {pull up lines as needed to make a line > margin length}
  1121.       if P^.lnLen <= beMargin+1 then repeat
  1122.         N := PLine(P^.dlNext);
  1123.         if (N = nil) then goto Breakout;
  1124.         if N^.lnLen > 0 then begin
  1125.           AscTrim(N^.St^, Temp^);
  1126.           InsertStr(' ', Temp^, 0);
  1127.           Status := N^.lnUpdate(Temp);
  1128.           if Status <> 0 then begin
  1129.             GotError(epNonFatal+ecOutOfMemory, emInsufficientMemory);
  1130.             exit;
  1131.           end;
  1132.  
  1133.           ConcatAsc(Work^,N^.St^,Temp^);
  1134.           MoveFast(Temp^,Work^,LenAsc(Temp^)+1);
  1135.           LList^.Delete(N);
  1136.         end;
  1137.       until (LenAsc(Work^) > beMargin+1) or (N^.lnLen = 0);
  1138.  
  1139.         {wrap the line and update it}
  1140.       WordWrap(Work, Temp, beMargin);
  1141.       Status := P^.lnUpdate(Work);
  1142.       if Status <> 0 then begin
  1143.         GotError(epNonFatal+ecOutOfMemory,emInsufficientMemory);
  1144.         exit;
  1145.       end;
  1146.       AscTrimLead(Temp^, Work^);
  1147.       if LenAsc(Work^) = 0 then begin
  1148.         ChLine(1);
  1149.         goto Breakout;
  1150.       end;
  1151.  
  1152.       if B > 0 then
  1153.         InsertStr(CharStr(' ', B), Work^, 0);
  1154.  
  1155.         {add the ovrlap line to the list}
  1156.       New(N,Init(Work));
  1157.       if N = nil then begin
  1158.         GotError(epNonFatal+ecOutOfMemory,emInsufficientMemory);
  1159.         exit;
  1160.       end;
  1161.       LList^.Place(N,P);
  1162.       P := PLine(P^.dlNext);
  1163.       ChLine(1);
  1164.       Inc(Q);
  1165.     end;
  1166.  
  1167. BreakOut:
  1168.     GetCurLine;
  1169.     CursorToCol(Cur^.lnLen);
  1170.     CleanBlocking;
  1171.     SetLongFlag(beOptions, beModified+beForceRedraw);
  1172.   end;
  1173.  
  1174.   procedure BigEditor.ReformatGlobal;
  1175.   var S : StreamStateRec;
  1176.       P : PLine;
  1177.   begin
  1178.     if not LongFlagIsSet(beOptions, beWordWrap) then exit;
  1179.  
  1180.     SaveStatePrim(S);
  1181.     P := LList^.OfsLine(Top,LOfs);
  1182.     while P^.dlNext <> nil do begin
  1183.       ReformatParagraph;
  1184.       UpdateContents;
  1185.       P := LList^.OfsLine(Top,LOfs);
  1186.     end;
  1187.     RestoreStatePrim(S);
  1188.     SetLongFlag(beOptions, beModified+beForceRedraw);
  1189.   end;
  1190.  
  1191.   procedure BigEditor.CenterLine;
  1192.   var
  1193.     I, J, Delta, Len : Integer;
  1194.   begin
  1195.     GetCurLine;
  1196.     if Cur^.lnLen = 0 then exit;
  1197.  
  1198.       {find the first non-blank}
  1199.     I := LeadingWhite(Cur);
  1200.  
  1201.       {length of actual text in string}
  1202.     Len := Cur^.lnLen-I;
  1203.  
  1204.       {can it be centered?}
  1205.     if Len >= beMargin then begin
  1206.       if I > 1 then begin
  1207.           {can't center it, but we can move it to the left margin}
  1208.         DeleteAsc(Work^, 0, I);
  1209.         CharsInserted(Cur, 0, -I);
  1210.       end;
  1211.     end
  1212.     else begin
  1213.         {calculate new starting column}
  1214.       J := (beMargin-Len) shr 1;
  1215.       Delta := J-I;
  1216.  
  1217.       if Delta > 0 then begin
  1218.         {insert extra spaces at beginning of line}
  1219.         InsertStr(CharStr(' ', Delta), Work^, 0);
  1220.         CharsInserted(Cur, 0, Delta);
  1221.       end
  1222.       else if Delta < 0 then begin
  1223.         {delete extra spaces at beginning of line}
  1224.         DeleteAsc(Work^, 0, Delta);
  1225.         CharsInserted(Cur, 0, -Delta);
  1226.       end;
  1227.     end;
  1228.  
  1229.       {update the line}
  1230.     Status := Cur^.lnUpdate(Work);
  1231.     if Status <> 0 then begin
  1232.       GotError(epNonFatal+ecOutOfMemory, emInsufficientMemory);
  1233.       exit;
  1234.     end;
  1235.     CursorToCol(Cur^.lnLen);
  1236.     SetLongFlag(beOptions, beModified);
  1237.   end;
  1238.  
  1239. {---------------------------------------------------------------------------}
  1240.  
  1241. {$IFDEF UseScrollBars}
  1242.   procedure BigEditor.UpdateScrollBars;
  1243.     {-Update horizontal and vertical scroll bars}
  1244.   begin
  1245.     if LList^.Size <> SaveCnt then begin
  1246.       ChangeAllScrollBars(0, (AbsMaxAsciiZ-Width-1), 1, LList^.Size);
  1247.       SaveCnt := LList^.Size;
  1248.     end;
  1249.     DrawAllSliders(COfs, TNum+LOfs);
  1250.   end;
  1251. {$ENDIF}
  1252.  
  1253.   procedure BigEditor.AdjustCursorToWindow;
  1254.     {-when resizing, make sure CurLine and cursor are within window}
  1255.   var
  1256.     X : Integer;
  1257.   begin
  1258.     while LOfs > Height-1 do
  1259.       ChLine(-1);
  1260.     X := CurCol;
  1261.     while (X) > Width do begin
  1262.       Dec(X);
  1263.       CursorToCol(X);
  1264.     end;
  1265.   end;
  1266.  
  1267. {$IFDEF UseMouse}
  1268.   function BigEditor.ProcessMouseCommand(Cmd : Byte) : Boolean;
  1269.     {-Process ccMouseSel/Auto command. Returns True to return control to user.}
  1270.   var
  1271.     L : LongInt;
  1272.     FramePos : FramePosType;
  1273.     HotCode : Byte;
  1274.     NeedUp, NeedDn : Boolean;
  1275.  
  1276.     procedure MouseSelect;
  1277.       {-Move cursor to position of mouse}
  1278.     var
  1279.       I : Integer;
  1280.     begin
  1281.       Cur := Top;
  1282.  
  1283.       I := MouseKeyWordY+MouseYLo-wYL;
  1284.       if I < LOfs then
  1285.         LOfs := I
  1286.       else begin
  1287.         Cur := CurLine;
  1288.         while LOfs < I do
  1289.           if Cur^.dlNext <> nil then begin
  1290.             Cur := PLine(Cur^.dlNext);
  1291.             Inc(LOfs);
  1292.           end
  1293.           else Dec(I);
  1294.       end;
  1295.  
  1296.       I := MouseKeyWordX+MouseXLo-Pred(wXL)-1;
  1297.       if I < 0 then I := 0;
  1298.       CursorToCol(I);
  1299.       if beOptionsAreOn(beHighlightCurr) then
  1300.         SetLongFlag(beOptions, beForceRedraw);
  1301.     end;
  1302.  
  1303.   begin
  1304.     ProcessMouseCommand := False;
  1305.     NeedUp := False;
  1306.     NeedDn := False;
  1307.  
  1308.     {determine position of mouse}
  1309.     EvaluateMousePos;
  1310.     L := PosResults(FramePos, HotCode);
  1311.  
  1312.     case HotCode of
  1313.       hsNone :           {not a hot spot}
  1314.         case FramePos of
  1315.           frInsideActive :       {inside window}
  1316.             MouseSelect;
  1317.  
  1318.           frTL..frRR :           {on the frame}
  1319.             ProcessMouseCommand := (LongFlagIsSet(wFlags, wAllMouseEvents)) and
  1320.                                      (Cmd <> ccMouseAuto);
  1321.  
  1322.           frInsideFrame,         {inside window frame but not in window boundaries}
  1323.           frOutsideFrame :       {outside window frame}
  1324.             ProcessMouseCommand := (LongFlagIsSet(wFlags, wAllMouseEvents)) and
  1325.                                        {don't let an auto kick us out}
  1326.                                      (Cmd <> ccMouseAuto);
  1327.         end;
  1328.  
  1329. {$IFDEF UseScrollBars}
  1330.       hsDecV :            {the decrement fixture of a vertical scroll bar}
  1331.         if LongFlagIsSet(beOptions, beMousePage) then
  1332.           ChTopLine(-(Height-1))
  1333.         else
  1334.           ChLine(-1);
  1335.       hsDecH :           {the decrement fixture of a horizontal scroll bar}
  1336.         if COfs > 0 then begin
  1337.           Dec(COfs);
  1338.           SetLongFlag(beOptions, beForceRedraw);
  1339.         end;
  1340.       hsIncV :           {the increment fixture of a vertical scroll bar}
  1341.         if LongFlagIsSet(beOptions, beMousePage) then
  1342.           ChTopLine(Height-1)
  1343.         else
  1344.           ChLine(1);
  1345.       hsIncH :           {the increment fixture of a horizontal scroll bar}
  1346.         if COfs < (AbsMaxAsciiZ - Width) then begin
  1347.           Inc(COfs);
  1348.           SetLongFlag(beOptions, beForceRedraw);
  1349.         end;
  1350.       hsBar :            {the slider portion of a scroll bar}
  1351.         case FramePos of
  1352.           frLL, frRR :   {vertical scroll bar}
  1353.             begin
  1354.               L := TweakSlider(FramePos, MouseKeyWordY+MouseYLo, L, 1);
  1355.               if L <= 1 then
  1356.                 {goto top of file}
  1357.                 TopOfFile
  1358.               else begin
  1359.                 if L >= LList^.Size then
  1360.                   {goto end of file}
  1361.                   EndOfFile
  1362.                 else
  1363.                   {goto specified line}
  1364.                   GoToLineNum(Integer(L));
  1365.               end;
  1366.             end;
  1367.           else begin     {horizontal scroll bar}
  1368.             COfs := TweakSlider(FramePos, MouseKeyWordX+MouseXLo, L, 1);
  1369.             SetLongFlag(beOptions, beForceRedraw);
  1370.           end;
  1371.         end;
  1372. {$ENDIF}
  1373.  
  1374.       hsSpot,            {a single character hot spot}
  1375.       hsRegion0..255 :   {a user-defined region relative to a frame}
  1376. {$IFDEF UseDrag}
  1377.         begin
  1378.           if NOT(HandleMousePress(Self) in [MoveHotCode, ResizeHotCode, ZoomHotCode]) then
  1379.             ProcessMouseCommand := (Cmd <> ccMouseAuto);
  1380.           AdjustCursorToWindow;
  1381.           SetLongFlag(beOptions, beForceRedraw);
  1382.           if LongFlagIsSet(beOptions, beInsert) then
  1383.             FatCursor
  1384.           else
  1385.             NormalCursor;
  1386.         end;
  1387. {$ELSE}
  1388.         ProcessMouseCommand := (Cmd <> ccMouseAuto);
  1389. {$ENDIF}
  1390.     end;
  1391.   end;
  1392. {$ENDIF}
  1393.  
  1394.   procedure BigEditor.beUpdateContents;
  1395.   var
  1396.     S : String;
  1397.     SLen : Byte absolute S;
  1398.     A : String;
  1399.     ALen : Byte absolute A;
  1400.     P : PLine;
  1401.     I : Integer;
  1402.     Wid : Byte;
  1403.     Hit : Byte;
  1404.     B   : Boolean;
  1405.  
  1406.     procedure DispStr(P : PLine; Ofst : Integer);
  1407.     var
  1408.       W, X, Y : Integer;
  1409.     begin
  1410.       FillChar(S[1], Wid, ' ');
  1411.       SLen := Wid;
  1412.       if (LongFlagIsSet(beOptions, beHighlightCurr)) and (Ofst = LOfs) then
  1413.         FillChar(A[1], Wid, HA)
  1414.       else
  1415.         FillChar(A[1], Wid, TA);
  1416.       ALen := Wid;
  1417.       if P = nil then exit;
  1418.  
  1419.       W := P^.lnLen;
  1420.       if (W <> 0) and (W >= COfs) then begin
  1421.         if (W - COfs) >= Wid then
  1422.           MoveFast(P^.St^[COfs], S[1], Wid)
  1423.         else if (W - COfs) > 0 then
  1424.           MoveFast(P^.St^[COfs], S[1], W - COfs);
  1425.       end;
  1426.  
  1427.         {fixup blocking}
  1428.       if LongFlagIsSet(beOptions, beBlockOn) then
  1429.         if P^.Blocked then begin
  1430.           if P = beBlockBegin.LP then begin
  1431.             if P = beBlockEnd.LP then begin
  1432.               X := beBlockBegin.CP - COfs + 1;
  1433.               if X < 1 then X := 1;
  1434.               Y := (beBlockEnd.CP - COfs + 1) - X;
  1435.               if Y >= Wid then
  1436.                 Y := Wid;
  1437.               if (Y > 0) then
  1438.                 FillChar(A[x], Y, BA);
  1439.             end
  1440.             else begin
  1441.               if COfs >= beBlockBegin.CP then
  1442.                 FillChar(A[1], Wid, BA)
  1443.               else begin
  1444.                 X := beBlockBegin.CP-COfs+1;
  1445.                 if X > 0 then
  1446.                   FillChar(A[x], Wid, BA);
  1447.               end;
  1448.             end;
  1449.           end
  1450.           else if P = beBlockEnd.LP then begin
  1451.             if COfs < beBlockEnd.CP then
  1452.               FillChar(A[1], beBlockEnd.CP-COfs, BA);
  1453.           end
  1454.           else
  1455.             FillChar(A[1], Wid, BA);
  1456.         end;
  1457.  
  1458.         {fixup ctrl chars}
  1459.       for X := 1 to Wid do begin
  1460.         if S[x] < #32 then begin
  1461.           S[x] := Chr(Byte(S[x]) or $40);
  1462.           A[x] := Chr(CA);
  1463.         end;
  1464.       end;
  1465.  
  1466.       if LongFlagIsSet(beOptions, beSearching) and (P = SearchLine) then begin
  1467.         X := CurCol;
  1468.         if LongFlagIsSet(beOptions, beHighlightBack) then
  1469.           FillChar(A[X-Length(beSearchSt)+2], Length(beSearchSt), MA)
  1470.         else
  1471.           FillChar(A[X+1], Length(beSearchSt), MA);
  1472.       end;
  1473.  
  1474.         {fixup beMarkers}
  1475.       if LongFlagIsSet(beOptions, beMarkersOn) then
  1476.         for X := 0 to MaxMarker do
  1477.           if beMarkers[x].LP = P then begin
  1478.             Y := beMarkers[x].CP - COfs;
  1479.             if (Y > 0) and (Y <= Wid) then begin
  1480.               S[y] := Chr(X + ord('0'));
  1481.               A[y] := Chr(MA);
  1482.             end;
  1483.           end;
  1484.     end;
  1485.  
  1486.   begin
  1487.     Wid := Width;
  1488.  
  1489. {$IFDEF UseMouse}
  1490.     HideMousePrim(B);
  1491. {$ENDIF}
  1492.  
  1493.     if LongFlagIsSet(beOptions, beForceRedraw) then begin
  1494.         {redraw the whole screen}
  1495.       P := Top;
  1496.       for I := wYL to wYH do begin
  1497.         DispStr(P, I-wYL);
  1498.         FastWriteAttr(S, I, wXL, A);
  1499.         if P <> nil then
  1500.           P := PLine(LList^.Next(P));
  1501.       end;
  1502.     end
  1503.     else begin
  1504.         {redraw just the current line}
  1505.       P := CurLine;
  1506.       DispStr(P, LOfs);
  1507.       FastWriteAttr(S, wYL+LOfs, wXL, A);
  1508.  
  1509.         {account for highlighting}
  1510.       if LongFlagIsSet(beOptions, beHighlightCurr) then begin
  1511.         if LOfs > 0 then begin
  1512.           DispStr(PLine(P^.dlPrev), LOfs-1);
  1513.           FastWriteAttr(S, wYL+LOfs-1, wXL, A);
  1514.         end;
  1515.         if LOfs < Hit-1 then begin
  1516.           DispStr(PLine(P^.dlNext), LOfs+1);
  1517.           FastWriteAttr(S, wYL+LOfs+1, wXL, A);
  1518.         end;
  1519.       end;
  1520.     end;
  1521.  
  1522.     GoToXYAbs(wXL+CPos-1, wYL+LOfs);
  1523.     if LongFlagIsSet(beOptions, beInsert) then
  1524.       FatCursor
  1525.     else
  1526.       NormalCursor;
  1527.  
  1528.     {$IFDEF UseScrollBars}
  1529.     UpdateScrollBars;
  1530.     {$ENDIF}
  1531.  
  1532.     if @beStatus <> nil then
  1533.       beStatus(@Self);
  1534.  
  1535. {$IFDEF UseMouse}
  1536.     ShowMousePrim(B);
  1537. {$ENDIF}
  1538.     ClearLongFlag(beOptions, beForceRedraw);
  1539.   end;
  1540.  
  1541.   procedure BigEditor.UpdateContents;
  1542.   begin
  1543.     beUpdateContents;
  1544.     StackWindow.UpdateContents;
  1545.   end;
  1546.  
  1547.   procedure BigEditor.NewFilePrompted;
  1548.   var
  1549.     PS : PathStr;
  1550.     FS : LongInt;
  1551.   begin
  1552.     PS := bePathName;
  1553.     if GetFile(0, 'New path:', True, True, False, False,
  1554.                80, beDefExt, PS) and(PS <> bePathName) then begin
  1555.       if LongFlagIsSet(beOptions, beModified) then
  1556.         if YesNo(0, 'Current file modified.  Save?', beYes, False) = beYes then
  1557.           SaveFile;
  1558.       ReadFile(PS, FS);
  1559.       SetLongFlag(beOptions, beForceRedraw);
  1560.     end;
  1561.   end;
  1562.  
  1563.